﻿#region

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Xml;
using HudsonMonitor.Notify;
using HudsonMonitor.Properties;
using Timer = System.Timers.Timer;

#endregion

namespace HudsonMonitor
{
    /// <summary>
    /// Code for main window. Here we enable the user to see the status of build(s) on hudson.
    /// </summary>
    public partial class MainWindow
    {
        private static MainWindow instancereference;
        private readonly ExampleTaskbarNotifier taskbarNotifier;
        private readonly Timer timer;

        /// <summary>
        /// Default constructor
        /// </summary>
        public MainWindow()
        {
            CheckForUninstall();
            instancereference = this;
            OverallStatus = Status.Unknown;

            timer = new Timer(Settings.Default.PollInterval*60000);
            timer.Elapsed += TimerElapsed;
            timer.Start();
            CheckHudsonStatus();
            taskbarNotifier = new ExampleTaskbarNotifier {StayOpenMilliseconds = 2000};

            Closing += MainWindowClosing;

            InitializeComponent();

            taskbarNotifier.Show();
            Visibility = Visibility.Hidden;

            // If it's the first time we run the program, show settings
            if (Settings.Default.FirstRun)
            {
                SettingsWindow settings = new SettingsWindow();
                settings.ShowDialog();
                Settings.Default.FirstRun = false;
                Settings.Default.Save();
            }
        }

        private static void CheckForUninstall()
        {
            string[] arguments = Environment.GetCommandLineArgs();
            foreach (string argument in arguments)
            {
                // To uninstall only use /x 
                // /u means remove or repair
                if (argument.Split('=')[0].Equals("/x", StringComparison.CurrentCultureIgnoreCase))
                {
                    string guid = argument.Split('=')[1];
                    string path = Environment.GetFolderPath(Environment.SpecialFolder.System);
                    ProcessStartInfo si = new ProcessStartInfo(path + "\\msiexec.exe", "/i " + guid);
                    Process.Start(si);
                    Application.Current.Shutdown();
                }
            }
        }
        private Status OverallStatus { get; set; }

        private void TimerElapsed(object sender, ElapsedEventArgs e)
        {
            CheckHudsonStatus();
        }

        /// <summary>
        ///   Gets a reference to the main window.
        /// </summary>
        /// <returns>An instance of the main window</returns>
        public static MainWindow GetReference()
        {
            return instancereference;
        }

        /// <summary>
        ///   Sets the statusbar message in the buttom of the main window
        /// </summary>
        /// <param name = "message">The message to display</param>
        public void SetStatusbarMessage(string message)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) delegate
                                                                                {
                                                                                    StatusBarItem itemReference =
                                                                                        GetReference().statusBar.Items[0
                                                                                            ] as StatusBarItem;
                                                                                    if (itemReference != null)
                                                                                        itemReference.Content = message;
                                                                                });
        }

        /// <summary>
        /// Sets the message shown in the popup window
        /// </summary>
        /// <param name="message">The message to show</param>
        private void SetMessage(string message)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) delegate
                                                                                {
                                                                                    taskbarNotifier.NotifyContent.Clear();
                                                                                    taskbarNotifier.NotifyContent.Add(
                                                                                        new NotifyObject(message,
                                                                                                         "Hudson Build Monitor"));

                                                                                    // Tell the TaskbarNotifier to open.
                                                                                    taskbarNotifier.Notify();
                                                                                });
        }

        /// <summary>
        ///   Sets the color of the status button
        /// </summary>
        /// <param name = "newColor">The new color to set</param>
        private void SetStatusButtonColor(Brush newColor)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                   (ThreadStart) delegate { GetReference().ButtonStatus.Background = newColor; });
        }

        /// <summary>
        ///   Checks the status of the hudson build server.
        /// </summary>
        private void CheckHudsonStatus()
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) DoCheck);
        }

        private void DoCheck()
        {
            NetUtils netHelper = new NetUtils();
            XmlDocument xml = netHelper.GetHudsonXml(Settings.Default.HudsonUrl + "/api/xml");

            if (xml != null)
            {
                XmlNodeList jobs = xml.GetElementsByTagName("job");

                string tempStatusMessage = "Hudson status updated at " + DateTime.Now.ToLocalTime() +
                                           Environment.NewLine;
                Status tempStatus = Status.Ok;
                if (jobs.Count > 0)
                {
                    int tempIndex = comboBoxProjects.SelectedIndex;

                    // If tempindex is -1 it's the first time the program has run, set it to first element in list
                    // If not, leave the previous selection
                    if (tempIndex == -1)
                        tempIndex = 1;

                    // Clear previous projects first
                    comboBoxProjects.Items.Clear();

                    // Add projects found
                    foreach (XmlNode currentNode in jobs)
                    {
                        if (currentNode != null)
                        {
                            string projectName = "Unknown";
                            string projectColor = "";
                            XmlNode node1 = currentNode.SelectSingleNode("name");
                            XmlNode node2 = currentNode.SelectSingleNode("color");
                            if (node1 != null)
                                projectName = node1.InnerText;
                            if (node2 != null)
                                projectColor = node2.InnerText;

                            AddProjectToList(projectName, projectColor);
                            tempStatusMessage += "Projekt " + projectName + " " + Utilities.StatusToString(projectColor) +
                                                 Environment.NewLine;

                            tempStatus = Utilities.StringToStatus(projectColor);
                            SetStatusButtonColor(Utilities.StringToBrush(projectColor));
                        }
                    }

                    comboBoxProjects.SelectedIndex = tempIndex;
                }
                else
                {
                    tempStatusMessage = "No projects found.";
                    SetStatusbarMessage(tempStatusMessage);
                }

                // Show message if it is anything but ok
                if (OverallStatus != Status.Ok)
                    SetMessage(tempStatusMessage);

                // Update statusbar to show the user when we checked last
                SetStatusbarMessage("Hudson status checked at " + DateTime.Now.ToLocalTime());
                SetOverallstatus(tempStatus);
                SetIcon(OverallStatus);
            }
        }

        /// <summary>
        ///   Adds a new combobox item to the list of projects.
        /// </summary>
        /// <param name = "name">The text to show in the item</param>
        /// <param name = "statusColor">The color, indicating the status of the project</param>
        private void AddProjectToList(string name, string statusColor)
        {
            ComboBoxItem newItem = new ComboBoxItem();
            StackPanel itemStackPanel = new StackPanel();
            Ellipse statusEllipse = new Ellipse();
            TextBlock itemText = new TextBlock();

            statusEllipse.Width = 10;
            statusEllipse.Height = 10;
            statusEllipse.Fill = Utilities.StringToBrush(statusColor);
            statusEllipse.Margin = new Thickness(0, 0, 4, 0);

            itemText.TextAlignment = TextAlignment.Center;
            itemText.Text = name;

            itemStackPanel.Orientation = Orientation.Horizontal;
            itemStackPanel.Children.Add(statusEllipse);
            itemStackPanel.Children.Add(itemText);

            newItem.Content = itemStackPanel;
            comboBoxProjects.Items.Add(newItem);
        }

        private void SetOverallstatus(Status newstatus)
        {
            OverallStatus = newstatus;
            labelStatus.Content = OverallStatus.ToString();
        }

        private void OnMenuSettingClicked(object sender, RoutedEventArgs e)
        {
            SettingsWindow settings = new SettingsWindow {Owner = this};
            settings.ShowDialog();
            if (settings.DialogResult == true)
            {
                timer.Start();
            }
        }

        private void OnAboutMenuItemClicked(object sender, RoutedEventArgs e)
        {
            About about = new About {Owner = this};
            about.ShowDialog();
        }

        private void ButtonStatusClick(object sender, RoutedEventArgs e)
        {
            CheckHudsonStatus();
        }

        private void NotifyIconDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
            {
                // Open the TaskbarNotifier
                taskbarNotifier.Notify();
            }
        }

        private void NotifyIconShowMessageClick(object sender, RoutedEventArgs e)
        {
            // Show the message
            taskbarNotifier.Notify();
        }

        private void NotifyIconOpenClick(object sender, RoutedEventArgs e)
        {
            // Show this window
            Visibility = Visibility.Visible;
            Activate();
        }

        private void NotifyIconExitClick(object sender, RoutedEventArgs e)
        {
            Close();
            Environment.Exit(0);
        }

        private void MainWindowClosing(object sender, CancelEventArgs e)
        {
            Visibility = Visibility.Collapsed;
            e.Cancel = true;
        }

        private void ButtonGoToPageClick(object sender, RoutedEventArgs e)
        {
            ComboBoxItem item = comboBoxProjects.SelectedItem as ComboBoxItem;
            if (item != null)
            {
                StackPanel panel = item.Content as StackPanel;
                if (panel != null)
                {
                    TextBlock block = (TextBlock) panel.Children[1];
                    Process.Start(Settings.Default.HudsonUrl + "/job/" + block.Text);
                }
            }
            else
            {
                MessageBox.Show(this, "No project selected", "No Project");
            }
        }

        /// <summary>
        /// Sets the icon based on the overall status of the hudson build server
        /// </summary>
        /// <param name="status">The status of the project</param>
        private void SetIcon(Status status)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) delegate
                                                                                {
                                                                                    BitmapImage bitmap =
                                                                                        new BitmapImage();
                                                                                    bitmap.BeginInit();

                                                                                    if (status != Status.Ok)
                                                                                        bitmap.UriSource =
                                                                                            new Uri(
                                                                                                "pack://application:,,,/Resources/hudsonicon_red.ico");
                                                                                    else
                                                                                        bitmap.UriSource =
                                                                                            new Uri(
                                                                                                "pack://application:,,,/Resources/hudsonicon.ico");

                                                                                    bitmap.EndInit();
                                                                                    if (NotifyIcon != null)
                                                                                    {
                                                                                        NotifyIcon.Icon = bitmap;
                                                                                        Icon = bitmap;
                                                                                    }
                                                                                });
        }
    }
}